package com.gk.courses.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.gk.courses.dao.CourseDao;
import com.gk.courses.model.Course;
import com.gk.courses.model.CourseException;
import com.gk.courses.model.Student;

@Service
@Transactional
public class CourseServiceImpl implements CourseService {

	@Override
	public Course getCourse(int id) {
		return courseDao.findById(id);
	}

	@Override
	public void saveCourse(Course course) {
		courseDao.save(course);
	}

	@Override
	public void enrollStudentInCourse(Course course, Student student) throws CourseException {
		course = getCourse(course.getCourseId()); // lazy instance
		student = studentService.getStudent(student.getId()); // load whole instance
		enforcePrerequisites(course, student);
		courseDao.enrollStudentInCourse(course, student);
	}

	@Override
	public List<Student> getEnrolledStudentsInCourse(Course course) {
		course = getCourse(course.getCourseId()); // lazy instance
		return new ArrayList<Student>(course.getStudents());
	}

	@Override
	public List<Course> getAllCourses() {
		return courseDao.findAll();
	}

	private void enforcePrerequisites(Course course, Student student) throws CourseException {
		List<Course> completed = studentService.getCompletedCourses(student);
		// Check for prerequesites
		List<Course> prereqs = course.getPrerequisites();
		for (Course _course : prereqs) {
			if (!completed.contains(_course)) {
				throw new CourseException("Prerequisites are not met.");
			}
		}
	}
	
	@Override
	public void registerPrerequisites(Course parentCourse, Course dependedCourse) {
		parentCourse = getCourse(parentCourse.getCourseId()); // lazy instance
		dependedCourse = getCourse(dependedCourse.getCourseId()); // lazy instance
		courseDao.updatePrerequisities(parentCourse, dependedCourse);		
	}

	@Override
	public List<Course> getPrerequisites(Course course) {
		course = getCourse(course.getCourseId()); // lazy instance
		return new ArrayList<Course>(course.getPrerequisites());
	}

	// ---------------------- injections --------------------------

	protected CourseDao courseDao;
	protected StudentService studentService;

	@Autowired
	public final void setCourseDao(CourseDao courseDao) {
		this.courseDao = courseDao;
	}

	@Autowired
	public final void setStudentService(StudentService service) {
		this.studentService = service;
	}

}
